package com.example.concurrent;

import java.util.concurrent.*;

public class Juc01_Executors {
    /**
     * 定时、周期执行任务线程池
     * 注意⚠️：线程池以单机环境来衡量的，若部署在分布式场景下，周期性任务则会重复触发
     *
     * 分布式调度定时任务场景可使用elastic-job、quartz、xxl-job
     */
    public static void main(String[] args) {
        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(3);

        /*示例一：异步延迟-延迟执行任务示例*/
        ScheduledFuture<Integer>  future = executorService.schedule(() -> {
            System.out.println("主任务-延迟3秒后执行并返回1");
            return 1;
        }, 3, TimeUnit.SECONDS);
        //提交延迟任务的线程会异步执行逻辑1、2；
        //**** 逻辑1
        //**** 逻辑2
        try {
            //获取主任务的执行结果->阻塞等待主任务，直到其延迟时间结束执行并返回值
            System.out.println(future.get());
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
        /**
         * 周期类线程使用场景：
         *  场景1：redis的看门狗
         *  场景2：nacos/eureka的心跳机制
         */
        /* 示例二 */
        executorService.scheduleAtFixedRate(() ->{
            System.out.println("在延迟1秒后，每隔2秒执行一次任务");
            //分析，若主任务执行超过2秒怎么办？若超过2秒，后续任务将会丢到DelayQueue中排队，待上一个任务执行完成后立即执行
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                System.out.println("若不捕获异常，而是抛出，将导致线程中断，后续任务将被丢弃");
            }
        }, 1, 2, TimeUnit.SECONDS);

        /* 示例三 */
        executorService.scheduleWithFixedDelay(() ->{
            System.out.println("在延迟1秒后，每隔2秒执行一次任务");
            //分析，若主任务执行超过2秒怎么办？若超过2秒，后续任务将会丢到BlockingQueue中排队
            //待上一个任务执行完成后,再次等待2秒后执行，而非立即执行
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                System.out.println("若不捕获异常，而是抛出，将导致线程中断，后续任务将被丢弃");
            }
        }, 1, 2, TimeUnit.SECONDS);
    }
}
